package com.boe.common.util;

import java.lang.reflect.Array;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import lombok.*;

public class ListUtil {
    public static boolean any(Object... value) {
        if (value == null) return false;
        return Array.getLength(value) > 0;
    }

    public static boolean any(Collection value) {
        return hasValue(value);
    }

    public static boolean hasValue(Collection value) {
        if (value == null) return false;
        return !value.isEmpty();
    }

    public static <T> T elementAt(Collection<T> list, Integer index) {
        var ret = list.stream().skip(index).findFirst();
        if (ret.isPresent()) {
            return ret.get();
        }
        return null;
    }

    public static boolean contains(Collection list, Object item) {
        return list.stream().anyMatch(it -> Objects.equals(it, item));
    }

    public static boolean contains(Object[] list, Object item) {
        return contains(Arrays.asList(list), item);
    }

    /**
     * 展开 数组的数组
     *
     * @param list
     * @param <T>
     * @return
     */
    public static <T> List<T> unwindWithList(List<? extends Collection<T>> list) {
        var ret = new ArrayList<T>();
        for (var i = 0; i < list.size(); i++) {
            var item = list.get(i);
            for (var j = 0; j < item.size(); j++) {
                ret.add(elementAt(item, j));
            }
        }
        return ret;
    }

    public static <T> List<T> fromArray(Object arrayObject) {
        var ret = new ArrayList<T>();

        for (var i = 0; i < Array.getLength(arrayObject); i++) {
            ret.add((T) Array.get(arrayObject, i));
        }

        return ret;
    }

    public static <T> List<T> unwindWithArray(List<T[]> list) {
        return unwindWithList(list.stream().map(it -> Arrays.asList(it)).collect(Collectors.toList()));
    }


    public static <T> boolean removeOf(Collection<T> list, Object item) {
        Iterator itr = list.iterator();
        Object ret = null;
        while (itr.hasNext()) {
            ret = itr.next();
            if (Objects.equals(ret, item)) {
                itr.remove();
                return true;
            }
        }
        return false;
    }

    /**
     * Java 默认的 remove 在移除索引时有大坑， 推荐使用 removeAt
     *
     * @param index
     * @param <T>
     * @return
     * @link https://www.geeksforgeeks.org/remove-element-arraylist-java/
     */
    public static <T> T removeAt(Collection<T> list, int index) {
        Iterator itr = list.iterator();
        var pos = -1;
        Object ret = null;
        while (itr.hasNext()) {
            pos++;
            ret = itr.next();
            if (pos == index) {
                itr.remove();
                break;
            }
        }
        return (T) ret;
    }

    public static <T> T removeLast(Collection<T> list) {
        if (list == null || list.size() == 0) return null;
        var lastIndex = list.size() - 1;
        return removeAt(list, lastIndex);
    }


    /**
     * 求交集
     *
     * @param value1
     * @param value2
     * @return
     */
    public static <T extends Comparable<? super T>> Set<T> intersect(Collection<T> value1, Collection<T> value2) {
        if (value1 == null || value2 == null) return new LinkedHashSet<>();
        if (value1.isEmpty() || value2.isEmpty()) return new LinkedHashSet<>();

        return value1.stream().filter(it -> value2.contains(it)).collect(Collectors.toSet());
    }


    public static <T> T firstOrNull(List<T> list, Function<T, Boolean> func) {
        if (list.size() == 0) return null;
        for (var it : list) {
            if (func.apply(it)) {
                return it;
            }
        }

        return null;
    }

}
